Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit c4668c83dc800d87e6db99deb45094cdfb96853f


Parents : eed826d
Author : Mark Qvist <mark@unsigned.io>
Date : 2025-11-24T13:37:28+01:00

Implemented in-call profile switching for telephony primitive

Changes

3 files changed, 28 insertions(+), 15 deletions(-)


Diff

diff --git a/LXST/Codecs/Codec2.py b/LXST/Codecs/Codec2.py
index b4ab5c5..ab37ebe 100644
--- a/LXST/Codecs/Codec2.py
+++ b/LXST/Codecs/Codec2.py
@@ -87,7 +87,9 @@ class Codec2(Codec):
def decode(self, frame_bytes):
frame_header = frame_bytes[0]
frame_bytes = frame_bytes[1:]
- frame_mode = self.HEADER_MODES[frame_header]
+
+ if frame_header in self.HEADER_MODES: frame_mode = self.HEADER_MODES[frame_header]
+ else: frame_mode = self.mode
if self.mode != frame_mode:
self.set_mode(frame_mode)

diff --git a/LXST/Network.py b/LXST/Network.py
index 5c0f2a2..a0b4468 100644
--- a/LXST/Network.py
+++ b/LXST/Network.py
@@ -128,10 +128,8 @@ class LinkSource(RemoteSource, SignallingReceiver):
else:
decoded_frame = self.codec.decode(frame[1:])
- if self.pipeline:
- self.sink.handle_frame(decoded_frame, self)
- else:
- self.sink.handle_frame(decoded_frame, self, decoded=True)
+ if self.pipeline: self.sink.handle_frame(decoded_frame, self)
+ else: self.sink.handle_frame(decoded_frame, self, decoded=True)
if FIELD_SIGNALLING in unpacked:
super()._packet(data=None, packet=packet, unpacked=unpacked)

diff --git a/LXST/Primitives/Telephony.py b/LXST/Primitives/Telephony.py
index b3ab536..217fe9f 100644
--- a/LXST/Primitives/Telephony.py
+++ b/LXST/Primitives/Telephony.py
@@ -451,11 +451,12 @@ class Telephone(SignallingReceiver):
if self.active_call:
if self.active_call.profile == profile: return
else:
- self.active_call.profile = profile
- self.transmit_codec = Profiles.get_codec(self.active_call.profile)
- self.target_frame_time_ms = Profiles.get_frame_time(self.active_call.profile)
- if not from_signalling: self.signal(Signalling.PREFERRED_PROFILE+self.active_call.profile, self.active_call)
- self.__reconfigure_transmit_pipeline()
+ if self.call_status == Signalling.STATUS_ESTABLISHED:
+ self.active_call.profile = profile
+ self.transmit_codec = Profiles.get_codec(self.active_call.profile)
+ self.target_frame_time_ms = Profiles.get_frame_time(self.active_call.profile)
+ if not from_signalling: self.signal(Signalling.PREFERRED_PROFILE+self.active_call.profile, self.active_call)
+ self.__reconfigure_transmit_pipeline()
def __select_call_profile(self, profile=None):
if profile == None: profile = Profiles.DEFAULT_PROFILE
@@ -543,7 +544,18 @@ class Telephone(SignallingReceiver):
self.dial_tone.stop()
def __reconfigure_transmit_pipeline(self):
- pass
+ if self.transmit_pipeline and self.call_status == Signalling.STATUS_ESTABLISHED:
+ self.audio_input.stop()
+ self.transmit_mixer.stop()
+ self.transmit_pipeline.stop()
+ self.transmit_mixer = Mixer(target_frame_ms=self.target_frame_time_ms, gain=self.transmit_gain)
+ self.audio_input = LineSource(preferred_device=self.microphone_device, target_frame_ms=self.target_frame_time_ms, codec=Raw(), sink=self.transmit_mixer, filters=self.active_call.filters)
+ self.transmit_pipeline = Pipeline(source=self.transmit_mixer,
+ codec=self.transmit_codec,
+ sink=self.active_call.packetizer)
+ self.transmit_mixer.start()
+ self.audio_input.start()
+ self.transmit_pipeline.start()
def __open_pipelines(self, identity):
with self.pipeline_lock:
@@ -557,15 +569,16 @@ class Telephone(SignallingReceiver):
RNS.log(f"Opening audio pipelines for call with {RNS.prettyhexrep(identity.hash)}", RNS.LOG_DEBUG)
if self.active_call.is_incoming: self.signal(Signalling.STATUS_CONNECTING, self.active_call)
- if self.use_agc: filters = [BandPass(250, 8500), AGC()]
- else: filters = [BandPass(250, 8500)]
+ if self.use_agc: self.active_call.filters = [BandPass(250, 8500), AGC()]
+ else: self.active_call.filters = [BandPass(250, 8500)]
self.__prepare_dialling_pipelines()
+ self.active_call.packetizer = Packetizer(self.active_call, failure_callback=self.__packetizer_failure)
self.transmit_mixer = Mixer(target_frame_ms=self.target_frame_time_ms, gain=self.transmit_gain)
- self.audio_input = LineSource(preferred_device=self.microphone_device, target_frame_ms=self.target_frame_time_ms, codec=Raw(), sink=self.transmit_mixer, filters=filters)
+ self.audio_input = LineSource(preferred_device=self.microphone_device, target_frame_ms=self.target_frame_time_ms, codec=Raw(), sink=self.transmit_mixer, filters=self.active_call.filters)
self.transmit_pipeline = Pipeline(source=self.transmit_mixer,
codec=self.transmit_codec,
- sink=Packetizer(self.active_call, failure_callback=self.__packetizer_failure))
+ sink=self.active_call.packetizer)
self.active_call.audio_source = LinkSource(link=self.active_call, signalling_receiver=self, sink=self.receive_mixer)
self.receive_mixer.set_source_max_frames(self.active_call.audio_source, 2)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────